﻿using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Cosmos.IL2CPU.Plugs;
using DimOS.Constants;
//using DimOS.DimL;
using DimOS.DimSH;
using DimOS.H;
using String = DimOS.Plugs.String;
using ValueType = DimOS.H.ValueType;

namespace DimOS.Plugs
{
    public class Convert
    {
        static readonly char[] Binhex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        static readonly string[] Hexbin = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" };
        

        //static readonly char[] HexChars = { 'A', 'B', 'C', 'D', 'E', 'F' };
        private const string HexCharacters = "ABCDEF";
        static readonly int[] HexNumeric = { 10, 11, 12, 13, 14, 15 };
        const int AsciiDiff = 48;

        public static float ToFloat(bool expression) { return expression ? 1 : 0; }

        public static bool ToBoolean(float expression) { return expression == 1; }

        //Method for converting a string to Int32
        public static int ToInt32(string expression)
        {
            expression = String.Trim(expression);
            if (expression == null) return 0;
            
            int result = 0;
            bool negative = expression[0] == '-';

            for (int i = negative ? 1 : (expression[0] == '+' ? 1 : 0); i < expression.Length; i++)
            {
                if ((expression[i] >= '0') && expression[i] <= '9')
                {
                    if (i > 0) result *= 10;
                    result += expression[i] - '0';
                }
                else if (expression[i] != Tokens.Space) break;
            }
            return negative ? result * -1 : result;
        }

        //Int32 from decimal to any base
        public static string DecimalToBase(string number, int numbase)
        {
            bool negative;
            if (number.IndexOf('-') != -1) { negative = true;
                number = String.Replace(number, "-", ""); }
            else negative = false;

            var dec = ToInt32(number); number = "";
            var result = new int[32]; var maxBit = 32;
            for (; dec > 0; dec /= numbase) result[--maxBit] = dec % numbase;
            
            for (int i = 0; i < result.Length; i++)
                if (result[i] >= 10) number +=
                HexCharacters[result[i] % 10];
                else number += result[i];

            number = String.TrimStart(number, '0');
            return negative ? "-" + number : number;
        }

        //Int32 from any base to decimal
        public static string BaseToDecimal(string number, int numbase)
        {
            bool negative;
            if (number.IndexOf('-') != -1) { negative = true;
                number = String.Replace(number, "-", ""); }
            else negative = false;

            var dec = 0; var product = 1;
            for (int i = number.Length - 1; i >= 0; i--, product *= numbase)
            {
                var index = number[i] - AsciiDiff;

                for (int j = 0; j < HexCharacters.Length; j++)
                    if (number[i] == HexCharacters[j])
                    { index = HexNumeric[j]; break; } 
                dec += (index * product);
            }
            number = dec.ToString();
            return negative ? "-" + number : number;
        }

        //Int32 from any base to any base
        public static string ToNumbase(string number, int sourceNumbase, int targetNumbase)
        { return DecimalToBase(BaseToDecimal(number, sourceNumbase), targetNumbase); }

        public static int ToInt32(float number)
        { var expression = number.ToString(); int index; try { 
          index = expression.IndexOf('.'); if (index == -1) index
          = expression.IndexOf(','); index = index == -1 ? ToInt32
          (expression) : ToInt32 (expression.Remove(index)); } catch
          (OverflowException) {index = Int32.MaxValue;} return index; }

        public static float ToFloat(string expression)
        {
            int length = expression.Length, start = 0, f = 1, i;
            float result = 0;
            bool isNegative = false;
            bool isFloat = false;
            if (expression[0] == '-')
            {
                isNegative = true;
                start = 1;
            }
            else if (expression[0] == '+') start = 1;
            for (i = start; i < length; i++)
            {
                if (expression[i] == '.' || expression[i] == ',') isFloat = true;
                else if ((expression[i] >= '0') && expression[i] <= '9')
                {
                    if (i > 0) result *= 10;
                    result += expression[i] - '0';
                    if (isFloat) f *= 10;
                }
                else if (expression[i] != Tokens.Space) break;
            }
            if (isNegative) result *= -1;
            if (isFloat) result /= f;
            return result;
        }

        public static List<Value> ToList(string expression)
        {
            if (String.Trim(expression) == "") return new List<Value>();
            var trim = String.Trim(expression); if (trim[0] == Tokens
            .ValueLeft && trim[trim.Length - 1] == Tokens.ValueRight)
            { var value = new Script(Script.Normalize(trim)).GetValue();
            if (value.Type == ValueType.List) return value.List; return
            new List<Value>{ value }; } var list = new List<Value> { new
            Value("") }; var trigger = false; for (int i = 0; i < trim
            .Length - 1; i++) if (trim[i] == Tokens.VerbatimString &&
            (!trigger || (trim[i - 1] != Tokens.MirrorLeft && trim[i - 1]
            != Tokens.MirrorRight))) trigger = !trigger; else if (!trigger
            && (trim[i] == Tokens.Space || trim[i] == Tokens.NewLine))
            list.Add(new Value("")); else list[list.Count- 1].String +=
            trim[i]; return list;
        }

        public static List<Value> ToList(Value value)
        {
            if (value.Type == ValueType.Number) return new List<Value> { new Value(value) };
            if (value.Type == ValueType.String) return ToList(value.String);
            if (value.Type == ValueType.List) return value.List.Clone();
            return new List<Value>();
        }
    }
}
